package model

import (
	"time"

	"gorm.io/gorm"
)

// Appointment 预约挂号表
type Appointment struct {
	ID              int64          `gorm:"primaryKey;autoIncrement" json:"id"`
	UserID          int64          `gorm:"index;not null;comment:用户ID" json:"userId"`
	DoctorID        int64          `gorm:"index;not null;comment:医生ID" json:"doctorId"`
	ScheduleID      int64          `gorm:"index;comment:排班ID" json:"scheduleId"`
	PatientID       int64          `gorm:"index;not null;comment:就诊人ID" json:"patientId"`
	VisitType       int            `gorm:"type:tinyint;default:1;comment:就诊类型 1:初诊 2:复诊" json:"visitType"`
	AppointmentDate string         `gorm:"type:varchar(20);not null;comment:预约日期" json:"appointmentDate"`
	TimeSlot        string         `gorm:"type:varchar(50);comment:时间段" json:"timeSlot"`
	Status          int            `gorm:"type:tinyint;default:1;comment:状态 1:待支付 2:待就诊 3:已完成 4:已取消" json:"status"`
	Fee             float64        `gorm:"type:decimal(10,2);not null;comment:挂号费" json:"fee"`
	ClinicAddress   string         `gorm:"type:varchar(200);comment:门诊地址" json:"clinicAddress"`
	Remark          string         `gorm:"type:varchar(500);comment:备注" json:"remark"`
	OrderID         int64          `gorm:"index;comment:订单ID" json:"orderId"`
	CreatedAt       time.Time      `json:"createdAt"`
	UpdatedAt       time.Time      `json:"updatedAt"`
	DeletedAt       gorm.DeletedAt `gorm:"index" json:"-"`
}

func (Appointment) TableName() string {
	return "appointments"
}

// Schedule 医生排班表
type Schedule struct {
	ID              int64          `gorm:"primaryKey;autoIncrement" json:"id"`
	DoctorID        int64          `gorm:"index;not null;comment:医生ID" json:"doctorId"`
	ScheduleDate    string         `gorm:"type:varchar(20);not null;comment:排班日期" json:"scheduleDate"`
	StartTime       string         `gorm:"type:varchar(20);not null;comment:开始时间" json:"startTime"`
	EndTime         string         `gorm:"type:varchar(20);not null;comment:结束时间" json:"endTime"`
	MaxAppointments int            `gorm:"not null;comment:最大预约数" json:"maxAppointments"`
	BookedCount     int            `gorm:"default:0;comment:已预约数" json:"bookedCount"`
	ClinicAddress   string         `gorm:"type:varchar(255);comment:门诊地址" json:"clinicAddress"`
	Period          int            `gorm:"type:tinyint;comment:时段 1:上午 2:下午 3:晚上" json:"period"`
	Fee             float64        `gorm:"type:decimal(10,2);not null;comment:挂号费" json:"fee"`
	CreatedAt       time.Time      `json:"createdAt"`
	UpdatedAt       time.Time      `json:"updatedAt"`
	DeletedAt       gorm.DeletedAt `gorm:"index" json:"-"`
}

func (Schedule) TableName() string {
	return "doctor_schedules"
}

// ==================== Appointment 模型方法 ====================

// Create 创建预约
func (a *Appointment) Create(db *gorm.DB) error {
	a.CreatedAt = time.Now()
	a.UpdatedAt = time.Now()
	return db.Create(a).Error
}

// GetByID 根据ID获取预约详情
func (a *Appointment) GetByID(db *gorm.DB, id, userID int64) error {
	return db.Where("id = ? AND user_id = ?", id, userID).First(a).Error
}

// GetListByUserID 获取用户的预约列表
func GetAppointmentListByUserID(db *gorm.DB, userID int64, status, page, pageSize int) ([]Appointment, int64, error) {
	var appointments []Appointment
	var total int64

	query := db.Model(&Appointment{}).Where("user_id = ?", userID)
	if status > 0 {
		query = query.Where("status = ?", status)
	}

	// 统计总数
	if err := query.Count(&total).Error; err != nil {
		return nil, 0, err
	}

	// 分页查询
	err := query.Scopes(Paginate(page, pageSize)).
		Order("id DESC").
		Find(&appointments).Error

	return appointments, total, err
}

// UpdateStatus 更新预约状态
func (a *Appointment) UpdateStatus(db *gorm.DB, status int) error {
	return db.Model(a).Updates(map[string]interface{}{
		"status":     status,
		"updated_at": time.Now(),
	}).Error
}

// Cancel 取消预约
func (a *Appointment) Cancel(db *gorm.DB) error {
	// 开启事务
	tx := db.Begin()

	// 更新预约状态为已取消
	if err := tx.Model(a).Updates(map[string]interface{}{
		"status":     4, // 已取消
		"updated_at": time.Now(),
	}).Error; err != nil {
		tx.Rollback()
		return err
	}

	// 如果有关联排班，减少已预约数
	if a.ScheduleID > 0 {
		tx.Model(&Schedule{}).
			Where("id = ?", a.ScheduleID).
			UpdateColumn("booked_count", gorm.Expr("booked_count - ?", 1))
	}

	return tx.Commit().Error
}

// ==================== Schedule 模型方法 ====================

// GetByID 根据ID获取排班信息
func (s *Schedule) GetByID(db *gorm.DB, id int64) error {
	return db.Where("id = ?", id).First(s).Error
}

// GetByDoctorID 获取医生的排班列表
func GetScheduleListByDoctorID(db *gorm.DB, doctorID int64, startDate, endDate string) ([]Schedule, error) {
	var schedules []Schedule
	query := db.Where("doctor_id = ?", doctorID)
	if startDate != "" {
		query = query.Where("schedule_date >= ?", startDate)
	}
	if endDate != "" {
		query = query.Where("schedule_date <= ?", endDate)
	}
	err := query.Order("schedule_date ASC, start_time ASC").Find(&schedules).Error
	return schedules, err
}

// IsAvailable 检查排班是否可预约
func (s *Schedule) IsAvailable() bool {
	return s.BookedCount < s.MaxAppointments
}

// IncrementBookedCount 增加已预约数
func (s *Schedule) IncrementBookedCount(db *gorm.DB) error {
	return db.Model(s).UpdateColumn("booked_count", gorm.Expr("booked_count + ?", 1)).Error
}
